package com.fingard.dsp.bank.helpers;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.fingard.FGBiz;
import com.fingard.client.DspClient;
import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDbHelper;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptMapping;
import com.fingard.dsp.bank.directConfig.FileSaveSet;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.reqrespobj.ReqRespHeader;
import com.fingard.dsp.interact.FileServerInvokerBase;
import com.fingard.dsp.interact.IFileServerInvoker;
import com.fingard.dsp.interact.UploadFileReq;
import com.fingard.dsp.interact.UploadFileResp;
import com.fingard.generalobj.ExecResponse;
import com.fingard.io.FileHelper;
import com.fingard.net.ConnState;
import com.fingard.net.FtpPortClient;
import com.fingard.net.FtpReceiver;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;

public class ReceiptFileSaveHelper {

	private FileSaveSet fileSet;
	private DirectBase dBase = null;
	private DataFileHelper dFileHelper = null;
	public ReceiptFileSaveHelper(DirectBase p_dBase) throws Exception{
		fileSet = FGBiz.dspCenter.dspConfig.getFileSaveSet("receipt");
		dBase = p_dBase;
		dFileHelper = new DataFileHelper(dBase);
	}
	
	/**检查配置*/
	public boolean checkSet(StringBuilder p_sb, String pBank){
		boolean retValue = true;
		if("remoteHost".equals(fileSet.saveType)){
			if(StringHelper.isNullOrEmpty(fileSet.mainHostServer)){
				p_sb.append("未配置回单主DSP服务地址\r\n");
				retValue = false;
	    	}
			p_sb.append("回单主DSP服务地址："+fileSet.mainHostServer+"\r\n");
		}else if("custom.fileServer".equals(fileSet.saveType)){
			if(StringHelper.isNullOrEmpty(FGBiz.dspCenter.dspSet.customCode)){
				p_sb.append("未配置客户代码<customCode>\r\n");
				retValue = false;
			}
		}else if("shareDir".equals(fileSet.saveType)){//-共享目录
			if(StringHelper.isNullOrEmpty(fileSet.shareDir)){
				p_sb.append("未配置共享目录<shareDir>\r\n");
				retValue = false;
			}
		}else{// if("localhost".equals(fileSet.saveType))
			String mainDir = fileSet.getMainDir(pBank);
			if(StringHelper.isNullOrEmpty(mainDir)){
				p_sb.append("未配置回单文件下载保存主目录\r\n");
				retValue = false;
	    	}
			p_sb.append("回单文件下载保存主目录："+mainDir+"\r\n");
		}
		
		if(StringHelper.isNullOrEmpty(FGBiz.dspCenter.dspSet.localDbFile)){
			p_sb.append("未配置本地数据库文件<localDbFile>\r\n");
			retValue = false;
		}
		
		return retValue;
	}
	
	private HashMap<String,HashMap<String,String>> mapSavedRecord = new HashMap<String,HashMap<String,String>>();
	private HashMap<String,String> getSavedRecordMap(Date p_date, String p_actNum, String p_fixStr) throws Exception{
		String key1 = p_actNum+"-"+Format.Date8Format.format(p_date)+p_fixStr;
		if(!mapSavedRecord.containsKey(key1)){
			//加载已经上传过的
			HashMap<String,String> mapDay = new HashMap<String,String>();
			String daySavedRdPath = dFileHelper.getBankReceiptSavedRecordFile(p_date, p_actNum, p_fixStr);
			File dataUpedFile = new File(daySavedRdPath);
			if(dataUpedFile.exists()){
				FileInputStream inputStream = null;
				BufferedReader bufferedReader = null;
				try{
					inputStream = new FileInputStream(daySavedRdPath);  
			        bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "gbk"));
			              
			        String str = null;
			        while((str = bufferedReader.readLine()) != null){
			            String[] eachkv = str.split(":");
			            if(eachkv.length>1){
			            	mapDay.put(eachkv[0], eachkv[1]);
			            }else{
			            	mapDay.put(eachkv[0], "");
			            }
			        }
				}catch(Exception e){
					throw(e);
				}finally{
					if(bufferedReader!=null){
						bufferedReader.close();
					}
					if(inputStream!=null){
						inputStream.close();
					}
				}
			}
			mapSavedRecord.put(key1, mapDay);
		}
		return mapSavedRecord.get(key1);
	}
	
    private DspClient dspClient = null;
    private IFileServerInvoker iFsInvoker = null;
	/*
	 * <!-- 配置说明
1、saveType如果是remoteHost-远程目录，配置mainHostServer；
2、saveType如果是localhost-本地目录，配置mainDir；
3、saveType如果是shareDir-共享目录，配置shareDir；
4、saveType如果是custom.fileServer-客制化文件服务器，配置uploadUrl和downloadUrl，还有上一级的customCode
 -->*/
	/**取DSPSystem.xml中的<fileSaveSet for="receipt">，判断如何保存文件
	 * @param p_header 请求头部
	 * @param pRcptMap 回单数据对象
	 * @param pLocalSrcFilePath 回单文件路径
	 * @throws Exception */
	public HelperResp saveByRcptMap(ReqRespHeader p_header, ReceiptMapping pRcptMap, String pLocalSrcFilePath) throws Exception{
		HelperResp resp = new HelperResp();
		Connection conn = null;
		FtpPortClient ftpClient = null;
		try{
			String chkKeyValue = pRcptMap.getKeyValue();
			String fixStrSavedRd = "saved";
			HashMap<String,String> mapSavedRd = getSavedRecordMap(pRcptMap.getBusDate(), pRcptMap.ownAct, fixStrSavedRd);
			if(mapSavedRd.containsKey(chkKeyValue)){
				resp.isCompleted = true;
				resp.appendMsgLn(chkKeyValue + "文件已经上传过，不再重复上传customFileId:" + mapSavedRd.get(chkKeyValue));
				return resp;
			}
			
			conn = FGBiz.getLocalDbConn();
			ReceiptMapping resultRcpt = ReceiptDbHelper.getRcptMpByOne(conn, pRcptMap);
			if(resultRcpt != null){
				resp.isCompleted = true;
				String msgPre = "busRef:"+resultRcpt.busRef+",receiptNo:"+resultRcpt.receiptNo+",askNumber:"+resultRcpt.askNumber;
				resp.appendMsgLn(msgPre + "文件已经上传过，不再重复上传customFileId:" + resultRcpt.customFileId);
				return resp;
			}
			
			String[] fvs = StringHelper.splitFileNameAndExt(pLocalSrcFilePath);
			String fileName = fvs[0];
			String fileExt = fvs[1];
			String fileExtAndDot;
			if(StringHelper.hasAnyChar(fileExt)){
				fileExtAndDot = "."+fileExt;
			}else{
				fileExtAndDot = "";
			}
			String nameAndExt = fileName+fileExtAndDot;
			String targetDir = "";
			String targetPath = "";
			String targetFileName;
			String keyForDirSp;
			if("1".equals(fileSet.fileNameFormat)){//文件名仅为参考号
				keyForDirSp = pRcptMap.getKeyValue();
				targetFileName = pRcptMap.getKeyValue()+fileExtAndDot;
			}else if("2".equals(fileSet.fileNameFormat) && StringHelper.hasAnyChar(pRcptMap.askNumber)){
				keyForDirSp = pRcptMap.reqBatchNo + "_" + pRcptMap.askNumber;
				targetFileName = keyForDirSp + fileExtAndDot;
			}else{
				keyForDirSp = pRcptMap.getKeyValue();
				targetFileName = pRcptMap.getKeyValue()+"_"+pRcptMap.ownAct+fileExtAndDot;
			}
			
			//if(FileType.receipt.equals(p_fileType)){//回单文件
				targetDir = StringHelper.getDirPathUsingSplitGiveUpLastOne(keyForDirSp, 3);
				targetPath = targetDir + File.separator + targetFileName;
			//}
				pRcptMap.receiptFile = targetPath;
			
			String customFileId = "";
			
			String cmpSaveType = "";
			if(StringHelper.hasAnyChar(fileSet.saveType)){
				cmpSaveType = fileSet.saveType.toLowerCase();
			}
			
			if(fileSet.ftpSet != null){
				resp.appendMsgLn("推送至ftp "+fileSet.ftpSet.serverIP);
				String upDir = StringHelper.trimEndFileSp(fileSet.ftpSet.upDir)+"/"+ pRcptMap.busDate;
				pRcptMap.customFileId = upDir +"/"+ pRcptMap.ownAct + "/" + pRcptMap.srcFile;
				ftpClient = new FtpPortClient(fileSet.ftpSet);
				ExecResponse execResp =ftpClient.connect();
				if(!execResp.isSucceed){
					resp.isCompleted = false;
					resp.appendMsgLn("连接ftp服务"+fileSet.ftpSet.serverIP+"失败："+execResp.logMsg);
					return resp;
				}
				//FTP的目录结构为：ftp主目录/日期/账号；
				execResp = ftpClient.makeDirIfNotExist(upDir);
				if(execResp.isSucceed){
					upDir = upDir+"/"+ pRcptMap.ownAct;
					execResp = ftpClient.makeDirIfNotExist(upDir);
					if(execResp.isSucceed){
						FtpReceiver rec = ftpClient.uploadFileToDir(pLocalSrcFilePath, upDir, pRcptMap.srcFile);
						if(rec.isCompleted){
							resp.appendMsgLn("推送至ftp成功");
						}else{
							resp.isCompleted = false;
							resp.appendMsgLn("推送至ftp失败："+rec.connMsg);
							return resp;
						}
					}else{
						resp.isCompleted = false;
						resp.appendMsgLn("创建ftp目录"+upDir+"失败："+execResp.logMsg);
						return resp;
					}
				}else{
					resp.isCompleted = false;
					resp.appendMsgLn("创建ftp目录"+upDir+"失败："+execResp.logMsg);
					return resp;
				}
				
			}
			
			if("remotehost".equals(cmpSaveType)){//发到远程DSP
				if(dspClient == null){
					dspClient = new DspClient(fileSet.mainHostServer);
					dspClient.timeoutSec = fileSet.getReadTimeoutSec(15, resp.sbMsg);
				}
				resp.appendMsgLn("文件"+nameAndExt+"推送至远程路径"+targetPath);
				String retXml = "";
				try {
					TcpReceiver retReceiver = dspClient.syncFile(pLocalSrcFilePath, FileType.receipt, p_header.bankCode,pRcptMap.bank, targetPath);
					if(retReceiver.isCompleted){
	    				retXml = new String(retReceiver.recBytes, retReceiver.contentStartIndex,retReceiver.contentLength, retReceiver.charsetName);
	    				XmlTextReader retXmlRd = new XmlTextReader(retXml);
	    				if("0".equals(retXmlRd.getSimpleText("RespCode"))){
	    					resp.isCompleted = true;
	    					resp.appendMsgLn("文件"+nameAndExt+"推送成功");
	    				}else{
	    					resp.appendMsgLn("文件"+nameAndExt+"推送失败，响应报文："+retXml);
	    				}
	    			}
	    			else{
	    				resp.appendMsgLn("文件"+nameAndExt+"推送失败："+retReceiver.getConnMsg());
	    				resp.connState = retReceiver.connState;
	    				if(retReceiver.connState.equals(ConnState.FAIL)){
	    					resp.appendMsgLn("连接主DSP服务"+fileSet.mainHostServer+"失败");
	    				}
	    			}
				} catch (Exception e) {
					resp.appendMsgLn(LogHelper.getStackTrace(e)+"\r\nretXml:"+retXml);
					FGBiz.limitMsg.exception("ReceiptFileSaveHelper", e);
				}
			}else if("custom.fileserver".equals(cmpSaveType) || "oss".equals(cmpSaveType)){
				//-客制化文件服务器或云OSS
				String chkCustomFileId = "";
				if("custom.fileserver".equals(cmpSaveType)){
					chkCustomFileId = ReceiptDbHelper.getCustomFileId(conn, pRcptMap);
				}
				if(StringHelper.hasAnyChar(chkCustomFileId)){
					resp.isCompleted = true;
					customFileId = chkCustomFileId;
					resp.appendMsgLn(pRcptMap.getKeyValue()+"文件"+nameAndExt+"之前已经上传，customFileId："+customFileId);
				}else{
					if(iFsInvoker==null){
						try {
		                    String className = "";
		                    if("custom.fileserver".equals(cmpSaveType)){
		                    	className = "com.fingard.dsp.interact.custom." + FGBiz.dspCenter.dspSet.customCode.toLowerCase() + "." + "FileServerInvoker";
		                    }else{
		                    	className = "com.fingard.dsp.interact.oss." + fileSet.ossSet.ossType.toLowerCase() + "." + "FileServerInvoker";
		                    }
		                    Class<?> fsClass = Class.forName(className);
		                    if (fsClass != null) {
		                    	FileServerInvokerBase fsClassBase = (FileServerInvokerBase) fsClass.newInstance();
		                    	fsClassBase.fsSet = this.fileSet;
		                    	if("custom.fileserver".equals(cmpSaveType)){
		                    		resp.appendMsgLn("uploadUrl:" + fileSet.uploadUrl);
			                    	resp.appendMsgLn("downloadUrl:" + fileSet.downloadUrl);
			                    	resp.appendMsgLn("username:" + fileSet.username);
			                    	resp.appendMsgLn("systemName:" + fileSet.systemName);	
		                    	}else{
		                    		resp.appendMsgLn("bucket:" + fileSet.ossSet.bucket);
		                    		resp.appendMsgLn("endpoint:" + fileSet.ossSet.endpoint);
		                    		resp.appendMsgLn("accessKeyId:" + fileSet.ossSet.accessKeyId);
		                    		resp.appendMsgLn("accessKeySecret:" + fileSet.ossSet.accessKeySecret);
		                    	}
		                        iFsInvoker = (IFileServerInvoker) fsClassBase;
		                    }
		                }catch (Throwable t) {
		                	resp.connState = ConnState.CLASS_NOT_FOUND;
		                	resp.appendMsgLn(LogHelper.getStackTrace(t));
		                	FGBiz.limitMsg.exception("ReceiptFileSaveHelper", t);
		                	return resp;
		                }
					}
					UploadFileReq upReq = new UploadFileReq();
					upReq.upFileLocalPath = pLocalSrcFilePath;
					UploadFileResp upResp = iFsInvoker.uploadFile(upReq);
					if(upResp.isCompleted){
						resp.isCompleted = true;
						resp.appendMsgLn("文件"+nameAndExt+"上传成功，rtnFileId："+upResp.rtnFileId);
						customFileId = upResp.rtnFileId;
						pRcptMap.customFileId = customFileId;
						if(!ReceiptDbHelper.saveCustomFileId(conn, pRcptMap)){
							resp.appendMsgLn("文件"+nameAndExt+"的上传记录保存本地数据库失败");
						}
					}else{
						resp.connState = upResp.connState;
						resp.sbMsg.append(upResp.sbMsg.toString());
					}
				}
			}else{//保存到本地目录或共享目录
				try{
					String tmpSaveToDir;
					if("shareDir".equals(fileSet.saveType)){//-共享目录
						tmpSaveToDir = fileSet.shareDir + File.separator + targetDir;
					}else{
						String mainDir = fileSet.getMainDir(pRcptMap.bank);
						tmpSaveToDir = mainDir + File.separator + targetDir;
					}
		            File copyToDir = new File(tmpSaveToDir);
		            if (!copyToDir.exists()) {
		                copyToDir.mkdirs();
		            }
		            //targetPath = targetDir + File.separator+pRcptMap.getKeyValue()+"_"+pRcptMap.ownAct+fileExtAndDot;
		            //targetPath = targetDir + File.separator+p_ref+"_"+p_act+fileExtAndDot;
		            String toFilePath = tmpSaveToDir + File.separator + targetFileName;
		            File eachToFile = new File(toFilePath);
		            //if (!eachToFile.exists()) {
		            //    eachToFile.createNewFile();
		            //}
		            resp.sbMsg.append("复制文件" + pLocalSrcFilePath + "至" + toFilePath+"\r\n");
		            File srcFile = new File(pLocalSrcFilePath);
		            FileHelper.copyFile(srcFile, eachToFile);
		            
		            resp.isCompleted = true;
				}catch(Exception ex){
					resp.appendMsgLn(LogHelper.getStackTrace(ex));
					FGBiz.limitMsg.exception("ReceiptFileSaveHelper", ex);
				}
			}
			
			if(resp.isCompleted){//回单文件 && FileType.receipt.equals(p_fileType)
				//String dataMapFile = targetDir+File.separator+"mapping"+"_"+pRcptMap.ownAct+".txt";
				//String receiptFileName = StringHelper.getFileName(pRcptMap.srcFile);
				//+ p_ref + fileExtAndDot;
				if(StringHelper.hasAnyChar(fileSet.mainHostServer)){
					resp.isCompleted = false;
					resp.sbMsg.append("保存回单映射数据至远程服务器");
					String fileContent = "<ATSYH><TransReq>\r\n<DataType>receipt</DataType><TransParam>\r\n"+pRcptMap.toXml()+"</TransParam>\r\n</TransReq></ATSYH>";
					if(dspClient == null){
						dspClient = new DspClient(fileSet.mainHostServer);
						dspClient.timeoutSec = fileSet.getReadTimeoutSec(15, resp.sbMsg);
					}
					String retXml = "";
					try {
						TcpReceiver retReceiver = dspClient.saveToDb(fileContent);
						if(retReceiver.isCompleted){
		    				retXml = new String(retReceiver.recBytes, retReceiver.contentStartIndex,retReceiver.contentLength, retReceiver.charsetName);
		    				XmlTextReader retXmlRd = new XmlTextReader(retXml);
		    				if("0".equals(retXmlRd.getSimpleText("RespCode"))){
		    					resp.isCompleted = true;
		    					resp.appendMsgLn("映射信息"+fileContent+"推送成功");
		    				}else{
		    					resp.appendMsgLn("映射信息"+fileContent+"推送失败，响应报文："+retXml);
		    				}
		    			}
		    			else{
		    				resp.appendMsgLn("映射信息"+fileContent+"推送失败："+retReceiver.getConnMsg());
		    				resp.connState = retReceiver.connState;
		    				if(retReceiver.connState.equals(ConnState.FAIL)){
		    					resp.appendMsgLn("连接主DSP服务"+fileSet.mainHostServer+"失败");
		    				}
		    			}
					} catch (Exception e) {
						resp.appendMsgLn(LogHelper.getStackTrace(e)+"\r\nretXml:"+retXml);
						FGBiz.limitMsg.exception("ReceiptFileSaveHelper", e);
					}
				}else{//存本地
					/*
					String tmpSaveToDir = fileSet.mainDir + File.separator + targetDir;
					dataMapFile = tmpSaveToDir+File.separator+"mapping"+"_"+p_act+".txt";
		            File toMkDir = new File(tmpSaveToDir);
		            if (!toMkDir.exists()) {
		            	toMkDir.mkdirs();
		            }
		            try {
						FileHelper.appendFile(dataMapFile, fileContent, "gbk");
						resp.isCompleted = true;
					} catch (Exception e) {
						resp.appendMsgLn(LogHelper.getStackTrace(e));
					}
		            */
					resp.isCompleted = true;
				}
			}
			if(resp.isCompleted){//存本地库
				//String daySavedRdPath = dFileHelper.getBankReceiptSavedRecordFile(p_date, p_act, fixStrSavedRd);
				//FileHelper.appendFile(daySavedRdPath, p_ref+":"+customFileId+"\r\n", "gbk");
				//mapSavedRd.put(p_ref,customFileId);
				
				boolean isAllSuccess = true;
				
				HashMap<String,String> otherList = pRcptMap.getOtherBusRef();
				if(otherList!=null && otherList.size()>0){
					String savedBusRef = pRcptMap.busRef;
					String savedReceiptNo = pRcptMap.receiptNo;
					Iterator<Map.Entry<String, String>> it = otherList.entrySet().iterator();
					while (it.hasNext()) {
	            	    Map.Entry<String, String> eachEntry = it.next();
	            	    pRcptMap.busRef = eachEntry.getKey();
	            	    pRcptMap.receiptNo = eachEntry.getValue();
						if(StringHelper.hasAnyChar(fileSet.mainHostServer)){
							String fileContent = "<ATSYH><TransReq>\r\n<DataType>receipt</DataType><TransParam>\r\n"+pRcptMap.toXml()+"</TransParam>\r\n</TransReq></ATSYH>";
							if(dspClient == null){
								dspClient = new DspClient(fileSet.mainHostServer);
								dspClient.timeoutSec = fileSet.getReadTimeoutSec(15, resp.sbMsg);
							}
							String retXml = "";
							try {
								
								TcpReceiver retReceiver = dspClient.saveToDb(fileContent);
								if(retReceiver.isCompleted){
				    				retXml = new String(retReceiver.recBytes, retReceiver.contentStartIndex,retReceiver.contentLength, retReceiver.charsetName);
				    				XmlTextReader retXmlRd = new XmlTextReader(retXml);
				    				if(!"0".equals(retXmlRd.getSimpleText("RespCode"))){
				    					resp.appendMsgLn("OtherBusRef:"+pRcptMap.busRef+"远程保存失败");
				    					FGBiz.limitMsg.add("ReceiptFileSaveHelper-OtherBusRef", "映射信息"+fileContent+"推送失败，响应报文："+retXml);
				    				}else{
				    					resp.appendMsgLn("OtherBusRef:"+pRcptMap.busRef+"远程保存成功");
				    				}
				    			}
				    			else{
				    				resp.appendMsgLn("OtherBusRef:"+pRcptMap.busRef+"远程保存失败");
				    				FGBiz.limitMsg.add("ReceiptFileSaveHelper-OtherBusRef", fileSet.mainHostServer+"映射信息"+fileContent+"推送失败："+retReceiver.getConnMsg());
				    			}
							} catch (Exception e) {
								isAllSuccess = false;
								FGBiz.limitMsg.exception("ReceiptFileSaveHelper-OtherBusRef", e);
								resp.appendMsgLn(LogHelper.getStackTrace(e));
								break;
							}
						}else{
							if(ReceiptDbHelper.saveReceiptMapping(conn, pRcptMap)){
								resp.appendMsgLn("OtherBusRef:"+pRcptMap.busRef+"本地保存成功");
							}else{
								isAllSuccess = false;
								resp.appendMsgLn("OtherBusRef:"+pRcptMap.busRef+"本地保存失败");
								break;
							}
						}
					}
					pRcptMap.busRef = savedBusRef;
					pRcptMap.receiptNo = savedReceiptNo;
				}
				if(isAllSuccess){
					ReceiptDbHelper.saveReceiptMapping(conn, pRcptMap);
				}
			}
		}catch(Exception ex){
			FGBiz.limitMsg.exception("ReceiptFileSaveHelper", ex);
			throw(ex);
		}finally{
			if(conn != null){
				try{
				conn.close();
				}catch(Exception ex){
					ex.printStackTrace();
				}
			}
			if(ftpClient!=null){
				ftpClient.disconnect();
			}
		}
		return resp;
	}
}
